<?php
/**
 * The world of warcraft armory library was created by Marc Binder. The called
 * product will be deployed by Tof Technologies, Germany. All sources contain to 
 * the New BSD Licence. Self created extensions can be contained in the hall of 
 * fame. So the community has the chance to get a overview of all parsers and
 * handlers, which are really effective.
 * 
 * Get more informations:
 * http://code.google.com/p/warcraftarmory/
 * 
 * @author      Marc Binder <marcandrebinder@gmail.com>
 * @copyright   (c) Tof Technologies, Germany - 2010
 * @license     New BSD Licence
 * @package     Wow_Armory
 * @version     $Id$
 */

/**
 * Wow_Armory_Parse
 * 
 * @category    Wow_Armory
 * @package     Parse
 * @subpackage  -
 * @example     n/A
 */
class Wow_Armory_Parse
{
    
    /**
     * Type guild.
     * 
     * @var string
     */
    const GUILD     = 'guild';
    
    /**
     * Type character.
     *  
     * @var string
     */
    const CHARACTER = 'character';
    
    /**
     * Includes the type as string.
     * 
     * @var string
     */
    protected $_type = null;
    
    /**
     * Includes all handlers.
     * 
     * @var array
     */
    protected $_handlers = array();
    
    /**
     * Contains the configuration.
     * 
     * @var Wow_Armory_Config
     */
    protected $_config = null;
    
    /**
     * Creates the object.
     * 
     * @param  string $type
     * @param  Wow_Armory_Config $config
     * @return void
     */
    public function __construct($type = self::CHARACTER, Wow_Armory_Config $config)
    {
        $this->_setType($type)
             ->_setConfig($config);
    }
    
    /**
     * Sets the type as a string.
     * 
     * @param  string $type
     * @return Wow_Armory_Parse
     */
    protected function _setType($type)
    {
        if ($type != self::GUILD
            && $type != self::CHARACTER
        ) {
            throw new Wow_Armory_Exception('', 1017);
        }
           
        $this->_type = $type;
        return $this;
    }
    
    /**
     * Gets the type as a string.
     * 
     * @return string
     */
    public function getType()
    {
        return $this->_type;
    }
    
    /**
     * Sets the configuration.
     * 
     * @param  Wow_Armory_Config $config
     * @return Wow_Armory_Parse
     */
    protected function _setConfig($config)
    {
        $this->_config = $config;
        return $this;
    }
    
    /**
     * Gets the configuration.
     * 
     * @return Wow_Armory_Config
     */
    public function getConfig()
    {
        return $this->_config;
    }
    
    /**
     * Adds a new handler.
     * 
     * @param  Wow_Armory_Core_Handler_Abstract $handler
     * @return Wow_Armory_Parse
     */
    public function addHandler(Wow_Armory_Core_Handler_Abstract $handler)
    {
        $this->_handlers[get_class($handler)] = $handler;
        return $this;
    }
    
    /**
     * Gets a handler by name.
     * 
     * @param  string $name
     * @return Wow_Armory_Core_Handler_Abstract
     */
    public function getHandler($name)
    {
        if (isset($this->_handlers[$name])) {
            return $this->_handlers[$name];
        }
        
        return null;
    }
    
    /**
     * Return all handlers.
     * 
     * @return array
     */
    public function getHandlers()
    {
        return $this->_handlers;
    }
    
    /**
     * Execute the commited commands.
     * 
     * @return Wow_Armory_Parse_Result
     */
    public function fetch()
    {
        $url = new Wow_Armory_Core_Url($this->getConfig());

        if (!is_null(Wow_Armory_Parse_Result_Need::getNeeds())) {
            
            if ($this->getConfig()->getCache()) {
                $cache = $this->getConfig()->getCacheHandler();
            }
            
            foreach (Wow_Armory_Parse_Result_Need::getNeeds() as $need) {
                if ($need == self::GUILD) {
                    $guildName = $this->getConfig()->getGuild()->getGuildName();
                    if (empty($guildName)) {
                        throw new Wow_Armory_Exception('', 1019);
                    }
                }
                
                $curl = new Wow_Armory_Core_Curl();
                $curl->init()
                     ->setUserAgent();
                
                $method = 'get' . ucfirst($need) . 'SheetUrl';
                
                if ($this->getConfig()->getCache()) {
                    $name    = $this->_getCacheName($method);
                    $element = $cache->load($name);
                }
                
                if ($this->getConfig()->getCache()
                    && $cache->isExpired($element)
                ) {
                    $load = true;
                } else {
                    $load = false;
                }
                
                if ($load) {
                    $curl->setUrl($url->$method());
                    $element = $curl->execute();

                    if ($this->getConfig()->getCache()) {
                        $cache->write($name, 3600, $element);
                    }
                }
                 
                $element = new Wow_Armory_Core_Element($element);
                Wow_Armory_Parse_Result_Registry::set($need, $element->toArray());
                unset($curl);
            }
        }
        
        $results = array();
        foreach ($this->getHandlers() as $class) {
            $results[get_class($class)] = $class->parse();
        }
        
        return new Wow_Armory_Parse_Result($results);
    }
    
    /**
     * Gets the cache name.
     * 
     * @param  string $method
     * @return string
     */
    protected function _getCacheName($method)
    {
        $name      = '';                    
        $character = $this->getConfig()->getCharacter();
        $guild     = $this->getConfig()->getGuild();
        $realm     = $this->getConfig()->getRealm();
        
        if ($character instanceof Wow_Armory_Character) {
            $name = $name . ucfirst($character->getCharacterName());
        }
        
        if ($guild instanceof Wow_Armory_Guild) {
            $name = $name . ucfirst($guild->getGuildNameParsed());
        }
        
        if ($realm instanceof Wow_Armory_Realm) {
            $name = $name . ucfirst($realm->getRealmNameParsed());
        }
        
        return $name . '-----' . $method;
    }
    
}